#ifndef _HELIX_PHYSICS_OBJECT_REPRESENTATION_H_
#define _HELIX_PHYSICS_OBJECT_REPRESENTATION_H_

#include "../../Helix.h"
#include "../../HObject.h"
#include "../../Log.h"
#include "../../Math/HelixMath.h"
#include "../HelixMesh.h"


namespace helix
{

	/**	This is a representation of the object.  Use it when creating a PhysObject that can be 
	*	represented more easily than by the actual mesh object that is rendered.
	*/
	class MY_CLASS PhysRepresentation
	{
	protected:
		float mass;
		Vector centerOfMass;

		int type;
		
	public:
		static const int POINT = 0;
		static const int SPHERE = 1;
		static const int BOX = 2;
		static const int PLANE = 3;

		/**	Default constructor, sets center of mass of object to <0,0,0>
		*	\mass the mass of the object
		*/
		PhysRepresentation(float mass)
		{
			this->mass = mass;
			centerOfMass = Vector(0.0f,0.0f,0.0f);
			type=POINT;
		}

		/** Constructor that allows you to specify an offset center of mass
		*	\mass the mass of the object
		*	\param centerOfMass a vector that specifies the offset (from <0,0,0>) from the center the object.
		*	\note Some physics engines do not support a centerOfMass offset for primitive shapes.  To get arround
		*	this, you can normally composite different shapes together using immovable joints.
		*/
		PhysRepresentation(float mass, Vector centerOfMass)
		{
			this->centerOfMass.setVector(centerOfMass);
			type=POINT;
		}

		/** destructor
		*/
		virtual ~PhysRepresentation()
		{
		}

		/**	Get the center of mass of the object
		*	\return a Vector specifying the center of mass (offset from the center of the object <0,0,0>)
		*/
		virtual Vector getCenterOfMass()
		{
			return centerOfMass;
		}

		/**	Get mass of the object
		*	\return a Vector specifying the center of mass (offset from the center of the object <0,0,0>)
		*/
		virtual float getMass()
		{
			return mass;
		}

		virtual int getType()
		{
			return type;
		}


	};

	/**	This is a representation of the object.  Use it when creating a PhysObject that can be
	*	easily represented as a sphere.
	*/
	class MY_CLASS SphereRepresentation : public PhysRepresentation
	{
	private:
		float radius;

	public:
		/** Create sphere with specified radius to use as a representation for the object
		*	\param radius the radius of the sphere
		*/
		SphereRepresentation(float mass,float radius) : PhysRepresentation(mass)
		{
			this->radius = radius;
			type=SPHERE;
		}

		/** Create sphere with specified radius and center of mass to use as a representation for the object
		*	\param centerOfMass a vector that specifies the offset (from <0,0,0>) from the center of mass
		*	of the object.
		*	\param radius the radius of the sphere
		*	\note Some physics engines do not support a centerOfMass offset for primitive shapes.  To get arround
		*	this, you can normally composite different shapes together using immovable joints.
		*/
		SphereRepresentation(float mass,Vector centerOfMass, float radius) : PhysRepresentation(mass,centerOfMass)
		{
			this->radius = radius;
			type=SPHERE;
		}

		/** destructor
		*/
		virtual ~SphereRepresentation()
		{
		}

		/**	Get the radius of the sphere
		*	\return the radius of the sphere
		*/
		float getRadius()
		{
			return radius;
		}
	};

	/**	This is a representation of the object.  Use it when creating a PhysObject that can be
	*	easily represented as a box.
	*/
	class MY_CLASS BoxRepresentation : public PhysRepresentation
	{
	private:
		float xLength;
		float yLength;
		float zLength;

	public:
		/** Create a box with specified lengths to use as a representation for the object
		*	\param xLength the length in the horizontal direction of the box (ends of the box will be at -xLength/2 and xLength/2)
		*	\param yLength the length in the vertical direction of the box (ends of the box will be at -yLength/2 and yLength/2)
		*	\param zLength the length in the depth direction of the box (ends of the box will be at -zLength/2 and zLength/2)
		*/
		BoxRepresentation(float mass,float xLength,float yLength,float zLength) : PhysRepresentation(mass)
		{
			this->xLength = xLength;
			this->yLength = yLength;
			this->zLength = zLength;

			type=BOX;
		}

		/** Create a box with specified lengths and center of mass to use as a representation for the object
		*	\param centerOfMass a vector that specifies the offset (from <0,0,0>) from the center of mass
		*	of the object.
		*	\param xLength the length in the horizontal direction of the box (ends of the box will be at -xLength/2 and xLength/2)
		*	\param yLength the length in the vertical direction of the box (ends of the box will be at -yLength/2 and yLength/2)
		*	\param zLength the length in the depth direction of the box (ends of the box will be at -zLength/2 and zLength/2)
		*	\note Some physics engines do not support a centerOfMass offset for primitive shapes.  To get arround
		*	this, you can normally composite different shapes together using immovable joints.
		*/
		BoxRepresentation(float mass,Vector centerOfMass, float xLength,float yLength,float zLength) : PhysRepresentation(mass,centerOfMass)
		{
			this->xLength = xLength;
			this->yLength = yLength;
			this->zLength = zLength;

			type=BOX;
		}

		/** destructor
		*/
		virtual ~BoxRepresentation()
		{
		}

		/**	Get the length in the X direction of the box
		*	\return the x length of the box
		*/
		float getXLength()
		{
			return xLength;
		}
		/**	Get the length in the X direction of the box
		*	\return the x length of the box
		*/
		float getYLength()
		{
			return yLength;
		}
		/**	Get the length in the X direction of the box
		*	\return the x length of the box
		*/
		float getZLength()
		{
			return zLength;
		}

	};

	/**	This is a representation of the object.  Use it when creating a PhysObject that can be
	*	easily represented as a plane.  
	*	\note Physics objects that are created as planes are always static.
	*/
	class MY_CLASS PlaneRepresentation : public PhysRepresentation
	{
	private:
		float a;
		float b;
		float c;
		float d;

	public:
		/** Create plane with specified parameters to use as a representation for the object
		*	\param a,b,c,d are from the planar equation:  a*x + b*y + c*z = d  Where  a b and c are the
		*	x y and z components of the normal vector of the plane, and d is the distance between the 
		*	origin and the plane (following the direction of the normal vector)
		*/
		PlaneRepresentation(float a, float b, float c, float d) : PhysRepresentation(0.0)
		{
			this->a = a;
			this->b = b;
			this->c = c;
			this->d = d;

			type=PLANE;
		}

		/** destructor
		*/
		virtual ~PlaneRepresentation()
		{
		}

		/**	Get the value of a in the plane equation 
		*	\return the value of a in the plane equation
		*/
		float getA()
		{
			return a;
		}

		/**	Get the value of b in the plane equation 
		*	\return the value of b in the plane equation
		*/
		float getB()
		{
			return b;
		}

		/**	Get the value of c in the plane equation 
		*	\return the value of c in the plane equation
		*/
		float getC()
		{
			return c;
		}

		/**	Get the value of d in the plane equation 
		*	\return the value of d in the plane equation
		*/
		float getD()
		{
			return d;
		}

	};

}

#endif